<?php
/**
 * Created by PhpStorm.
 * User: BlueIdeaLirui
 * Date: 2019/09/04
 * Time: 14:58
 */

namespace business\elasticsearch\services;

use business\elasticsearch\caches\LandCache;
use business\elasticsearch\repositories\LandRepository;
use business\elasticsearch\types\LandUsageType;
use common\utils\DateTimeUtils;
use common\utils\RedisUtil;

class LandService
{
    const REDIS_LAND_TAKE         = 'land_take';
    const REDIS_LAND_CONSTRUCTION = 'land_construction';
    const REDIS_LAND_PROJECT      = 'land_project';

    // =========================================== 市场数据-地块数据 ================================================ //
    /**
     * 市场数据-地块数据列表
     * @param int $page
     * @param int $pageSize
     * @return array
     */
    public function getBlockDataList(
        $page = 0,
        $pageSize = 0
    ) {
        $query = [];

        $include = ['uid', 'developer_uid', 'company_name', 'land_usage', 'take_land_price', 'area', 'take_land_date'];

        $landUsages = LandUsageType::$usage;

        $data = $tmp = [];

        if (!empty($landUsages)) {
            foreach ($landUsages as $key => $landUsage) {
                // 构建总量查询条件
                $subQuery = static::constructingBlockDataTotalQueryConditions($query, $landUsage);
                list($total, $result) = (new LandRepository())->queryLandTakeList(
                    $subQuery, $include, $aggregations = static::constructingBlockDataTotalAggregation());
                $tmp[$key] = current($result)['value'];
            }
        }

        list($total, $areaData) = (new LandRepository())->queryLandTakeList(
            $query, $include, $aggregations = static::constructingBlockDataTotalAggregation());

        $totalArea = !empty($areaData) ? current($areaData)['value'] : 0;

        if (!empty($tmp)) {
            foreach ($tmp as $k => $v) {
                $data[] = [
                    'usages'     => $k,
                    'area'       => round($v, 2),
                    'proportion' => round(($v / $totalArea) * 100),
                    'unit'       => '%'
                ];
            }
        }

        $proportions = array_column($data,'proportion');
        array_multisort($proportions,SORT_DESC, $data);

        return !empty($data) ? array_slice($data, ($page - 1) * $pageSize, $pageSize) : [];
    }

    /**
     * 构建市场数据-地块数据查询条件
     * @param array $query
     */
    protected static function constructingBlockDataTotalQueryConditions(
        &$query = [],
        $landUsage = []
    ) {
        $subQuery = [];

        if (!empty($landUsage)) {
            foreach ($landUsage as $value) {
                $query['bool']['should'][] = [
                    'match_phrase' => [
                        'land_usage.keyword' => $value
                    ]
                ];
                $subQuery['bool']['should'][] = [
                    'match_phrase' => [
                        'land_usage.keyword' => $value
                    ]
                ];
            }
        }

        return $subQuery;
    }

    /**
     * 构建市场数据-地块数据-聚合
     * @return array
     */
    protected static function constructingBlockDataTotalAggregation()
    {
        return [
            [
                'name' => 'totalarea',
                'options' => [
                    'sum' => [
                        'field' => 'area'
                    ]
                ]
            ]
        ];
    }
    // =========================================== 市场数据-地块数据 ================================================ //

    // ===================================== 市场数据-全年拿地数量月度分布 ========================================== //
    public function getTakeLandAllYearRroundList()
    {
        $query = [];

        // 构建查询条件
        static::constructingTakeLandAllYearRroundQueryConditions($query);

        $include = ['uid', 'developer_uid', 'company_name', 'land_usage', 'take_land_price', 'area', 'take_land_date'];

        list($total, $data) = (new LandRepository())->queryLandTakeList(
            $query, $include, $aggregations = static::constructingTakeLandAllYearRroundAggregation());

        $bucketsList = $data['group_by_time']['buckets'];

        $result = static::filterTakeLandAllYearRround($bucketsList);

        return $result;
    }

    /**
     * 过滤数据
     * @param array $buckets
     * @return array
     */
    protected static function filterTakeLandAllYearRround($buckets = [])
    {
        if (!empty($buckets)) {
            $data = [];
            foreach ($buckets as $value) {
                $tmp['date']         = $value['key_as_string'];
                $tmp['total_count']  = $value['doc_count'];
                $data[]              = $tmp;
            }

            return $data;
        }

        return [];
    }

    /**
     * 构建全年土地查询条件
     * @param array $query
     */
    protected static function constructingTakeLandAllYearRroundQueryConditions(
        &$query = []
    ) {
        $startTime = date('Y-01-01', strtotime("-1 month", DateTimeUtils::time()));
        $endTime   = date('Y-12-31', DateTimeUtils::time());
        // 构建时间周期查询
        static::constructingTakeLandDateQueryConditions($query, $startTime, $endTime);
    }

    /**
     * 构建全年土地-聚合
     * @param int $size
     * @return array
     */
    protected static function constructingTakeLandAllYearRroundAggregation()
    {
        return [
            [
                'name' => 'group_by_time',
                'options' => [
                    'date_histogram' => [
                        'field' => 'take_land_date',
                        'interval' => 'month',
                        'format' => 'yyyy-MM',
                        'min_doc_count' => 0
                    ]
                ]
            ]
        ];
    }
    // ===================================== 市场数据-全年拿地数量月度分布 ========================================== //

    // =========================================== 市场数据-土地数据 ================================================ //
    /**
     * 市场数据-土地数据列表
     * @param string $takeLandStartDate
     * @param string $takeLandEndDate
     * @param string $landUsage
     * @param $page
     * @param $pageSize
     * @return array
     */
    public function getLandTakeList(
        $region = '',
        $takeLandStartDate = '',
        $takeLandEndDate = '',
        $landUsage = '',
        $page,
        $pageSize,
        $id = 0,
        $isTotalQuantity = true
    ) {
        $page = max($page, 1);

        $query = [];

        // 构建查询条件
        static::constructingLandUsageQueryConditions(
            $query, $region, $takeLandStartDate, $takeLandEndDate, $landUsage);

        $queryKey = md5(serialize($query));

        $rtnList = LandCache::getListByHash(static::REDIS_LAND_TAKE . $queryKey, $page, $pageSize);

        if (!empty($rtnList['data'])) {
            $result['resultNum'] = (int)$rtnList['page']['count'];
            $list = RedisUtil::RedisFilterList($rtnList['data']);

            $additionalParms = [];

            foreach (
                [
                    'total_count', 'total_area', 'total_fee'
                ] as $item) {
                $additionalParms[
                    preg_replace_callback('/_+([a-z])/', function($matches){
                        return strtoupper($matches[1]);
                    }, $item)
                ] = LandCache::getRecordByString(static::REDIS_LAND_TAKE . '_' . $item . $queryKey, $id);
            }
            extract($additionalParms);
        } else {
            $from = ($page - 1) * $pageSize;

            $include = ['uid', 'developer_uid', 'company_name', 'land_usage', 'take_land_price', 'area', 'take_land_date'];

            list($total, $data) = (new LandRepository())->queryLandTakeList(
                $query, $include, $aggregations = static::constructingLandUsageAggregation($page, $pageSize, $isTotalQuantity));

            $result = ['resultNum' => $data['aggregations']['sum_other_doc_count']??0, 'resultSet' => []];

            if (empty($aggregations)) {
                if (!empty($data)) {
                    foreach ($data as $values) {
                        $result['resultSet'][] = $values['_source'];
                    }
                }
            } else {

                $totalCount  = $total;
                $totalArea   = round($data['totalarea']['value'], 2);
                $totalFee    = round($data['totalfee']['value'], 2);

                if ($isTotalQuantity) {
                    $bucketsList = static::filterLandTake($data['aggregations']['buckets']);
                    $rtnList = LandCache::getListByHash(static::REDIS_LAND_TAKE . $queryKey, $page, $pageSize);

                    if (empty($rtnList['data'])) {
                        if (!empty($bucketsList)) {
                            foreach ($bucketsList as $k => $v) {
                                LandCache::saveRecordByHash(static::REDIS_LAND_TAKE . $queryKey, $k, $v);
                            }

                            foreach (
                                [
                                    'total_count' => $totalCount, 'total_area' => $totalArea, 'total_fee' => $totalFee
                                ] as $key => $item) {
                                LandCache::saveRecordByString(static::REDIS_LAND_TAKE . '_' . $key . $queryKey, $id, $item);
                            }

                            $rtnList = LandCache::getListByHash(static::REDIS_LAND_TAKE . $queryKey, $page, $pageSize);
                        }
                    }

                    $result['resultNum'] = (int)$rtnList['page']['count'];
                    $list = RedisUtil::RedisFilterList($rtnList['data']);
                } else {
                    $bucketsList = array_slice($data['aggregations']['buckets'], $from, $pageSize);
                    $list        = static::filterLandTake($bucketsList);
                }
            }
        }

        $result['resultSet'] = [
            'totalCount' => (int)$totalCount, 'totalArea' => (int)$totalArea, 'totalFee' => (int)$totalFee, 'list' => $list
        ];

        return $result;
    }

    /**
     * 过滤数据
     * @param array $buckets
     * @return array
     */
    protected static function filterLandTake($buckets = [])
    {
        if (!empty($buckets)) {
            $data = [];
            foreach ($buckets as $value) {
                $tmp['developer_uid'] = $value['last_developer_uid']['value'];
                $tmp['company_name']  = $value['key'];

                $LastTakeLandDate = (new \business\datacenter\repositories\LandRepository())
                    ->getLandTakeOne(
                        [
                            'is_deleted' => 0,
                            'developer_uid' => (int)$tmp['developer_uid'],
                        ],
                        'take_land_date',
                        ['take_land_date' => SORT_DESC]
                    )['take_land_date'];

                $withinMonth = DateTimeUtils::formatDate(strtotime($LastTakeLandDate));

                $tmp['take_land_tag'] = !empty($LastTakeLandDate) && $withinMonth == '一个月内' ?
                    sprintf('近%s拿地', DateTimeUtils::formatDate(strtotime($LastTakeLandDate))) : '';

                $tmp['days']          = DateTimeUtils::getTimeDiff(DateTimeUtils::time(), strtotime($LastTakeLandDate));
                $tmp['total_count']   = $value['doc_count'];
                $tmp['total_area']    = round($value['totalarea']['value'], 2);
                $tmp['total_fee']     = round($value['totalfee']['value'], 2);
                $tmp['usage']         = static::mergeLandUsage($value['usage']['buckets']);
                $data[]               = $tmp;
            }

            return $data;
        }

        return [];
    }

    /**
     * 合并土地用途分类
     * @param array $source
     * @return array
     */
    protected static function mergeLandUsage($buckets = [])
    {
        if (!empty($buckets)) {
            $names = [];
            foreach ($buckets as $key => $value) {
                if (($name = static::searchLandUsageType($value['key'])) != '') {
                    if (empty($names[$name]['count'])) {
                        $names[$name]['count'] = 0;
                    }
                    $names[$name]['count'] = intval($names[$name]['count']) + $value['doc_count'];
                }
            }

            return $names;
        }

        return [];
    }

    /**
     * 查找土地用途分类对应关系
     * @param string $type
     * @return int|string
     */
    protected static function searchLandUsageType($type = '')
    {
        if (!empty($type)) {
            $landUsageType = LandUsageType::$usage;
            if (!empty($landUsageType)) {
                foreach ($landUsageType as $key => $value) {
                    foreach ($value as $item) {
                        if ($type == $item) {
                            return $key;
                        }
                    }
                }
            }
        }

        return '';
    }

    /**
     * 构建大数据拓客--拿地数据-拿地时间查询条件
     * @param string $takeLandDate
     * @return array
     */
    protected static function constructingTakeLandDateQueryConditions(
        &$query = [],
        $takeLandStartDate = '',
        $takeLandEndDate = ''
    ) {
        // 构建时间周期查询
        if (!empty($takeLandStartDate)
            && !empty($takeLandEndDate)) {
            $query['bool']['must'][] = [
                'range' => [
                    'take_land_date' => [
                        'gte' => $takeLandStartDate,
                        'lte' => $takeLandEndDate
                    ]
                ]
            ];
        }
    }

    /**
     * 构建大数据拓客--拿地数据-查询条件
     * @param array $query
     * @param string $takeLandStartDate
     * @param string $takeLandEndDate
     * @param string $landUsage
     */
    protected static function constructingLandUsageQueryConditions(
        &$query = [],
        $region = '',
        $takeLandStartDate = '',
        $takeLandEndDate = '',
        $landUsage = ''
    ) {

        if (!empty($takeLandStartDate) && !empty($takeLandEndDate)) {
            // 构建时间周期查询
            static::constructingTakeLandDateQueryConditions(
                $query,
                date('Y-m-01', strtotime($takeLandStartDate)), date('Y-m-t', strtotime($takeLandEndDate)));
        }

        $bool = [];

        // 构建项目地区查询
        if (!empty($region)) {
            $region = explode(',', $region);
            foreach ($region as $item) {
                $bool[0]['bool']['should'][] = [
                    'match_phrase' => [
                        'city' => $item
                    ]
                ];
                $bool[0]['bool']['should'][] = [
                    'match_phrase' => [
                        'city_code.keyword' => $item
                    ]
                ];
                $bool[0]['bool']['should'][] = [
                    'match_phrase' => [
                        'province' => $item
                    ]
                ];
                $bool[0]['bool']['should'][] = [
                    'match_phrase' => [
                        'province_code.keyword' => $item
                    ]
                ];
            }
        }

        // 构建项目用途查询
        if (!empty($landUsage)) {
            $landUsage = explode(',', $landUsage);
            $usages    = [];
            foreach ($landUsage as $usage) {
                $subclass = LandUsageType::$usage[$usage];
                if (!empty($subclass)) {
                    foreach ($subclass as $name) {
                        $usages[] = $name;
                    }
                } else {
                    $usages[] = $usage;
                }
            }

            if (!empty($usages)) {
                foreach ($usages as $value) {
                    $bool[1]['bool']['should'][] = [
                        'match_phrase' => [
                            'land_usage.keyword' => $value
                        ]
                    ];
                }
            }
        }

        $query['bool']['must'][] = $bool;
    }

    /**
     * 构建大数据拓客--拿地数据-聚合
     * @param int $size
     * @return array
     */
    protected static function constructingLandUsageAggregation($page, $pageSize, $isTotalQuantity = true)
    {
        $size = $page * $pageSize;
        return [
            [
                'name' => 'totalarea',
                'options' => [
                    'sum' => [
                        'field' => 'area'
                    ]
                ]
            ],
            [
                'name' => 'totalfee',
                'options' => [
                    'sum' => [
                        'field' => 'take_land_price'
                    ]
                ]
            ],
            [
                'name' => 'aggregations',
                'options' => [
                    'terms' => [
                        'field' => 'company_name.keyword',
                        //'execution_hint' => 'map',
                        'order' => [
                            'totalarea' => 'desc'
                        ],
                        'size' => $isTotalQuantity ? pow(2,31) - 1 : $size,
                        //'collect_mode' => 'breadth_first',
                    ],
                    'aggregations' => [
                        'last_developer_uid' => [
                            'max' => [
                                'field' => 'developer_uid'
                            ]
                        ],
                        'totalarea' => [
                            'sum' => [
                                'field' => 'area'
                            ]
                        ],
                        'totalfee' => [
                            'sum' => [
                                'field' => 'take_land_price'
                            ]
                        ],
                        'usage' => [
                            'terms' => [
                                'field' => 'land_usage.keyword',
                                'size'  => pow(2,31) - 1
                            ],
                        ]
                    ]
                ]
            ]
        ];
    }
    // =========================================== 市场数据-土地数据 ================================================ //

    // =========================================== 市场数据-开工数据 ================================================ //
    /**
     * 市场数据-开工数据列表
     * @param string $region
     * @param string $contractStartTime
     * @param string $contractEndTime
     * @param $page
     * @param $pageSize
     * @return array
     */
    public function getLandConstructionList(
        $region = '',
        $contractStartTime = '',
        $contractEndTime = '',
        $page,
        $pageSize,
        $id = 0,
        $isTotalQuantity = true
    ) {
        $page = max($page, 1);
        $query = [];

        // 构建查询条件
        static::constructingLandConstructionQueryConditions(
            $query, $region, $contractStartTime, $contractEndTime);

        $queryKey = md5(serialize($query));

        $rtnList = LandCache::getListByHash(static::REDIS_LAND_CONSTRUCTION . $queryKey, $page, $pageSize);

        if (!empty($rtnList['data'])) {
            $result['resultNum'] = (int)$rtnList['page']['count'];
            $list = RedisUtil::RedisFilterList($rtnList['data']);

            $additionalParms = [];

            foreach (
                [
                    'total_count', 'total_area', 'total_fee'
                ] as $item) {
                $additionalParms[
                preg_replace_callback('/_+([a-z])/', function($matches){
                    return strtoupper($matches[1]);
                }, $item)
                ] = LandCache::getRecordByString(static::REDIS_LAND_CONSTRUCTION . '_' . $item . $queryKey, $id);
            }
            extract($additionalParms);
        } else {
            $from = ($page - 1) * $pageSize;

            $include = ['uid', 'developer_uid', 'company_name', 'issuing_time', 'contract_price', 'area'];

            list($total, $data) = (new LandRepository())->queryLandConstructionList(
                $query, $include, $aggregations = static::constructingLandConstructionAggregation($page, $pageSize, $isTotalQuantity));

            $result = ['resultNum' => $data['aggregations']['sum_other_doc_count']??0, 'resultSet' => []];

            if (empty($aggregations)) {
                if (!empty($data)) {
                    foreach ($data as $values) {
                        $result['resultSet'][] = $values['_source'];
                    }
                }
            } else {

                $totalCount  = $total;
                $totalArea   = round($data['totalarea']['value'], 2);
                $totalFee    = round($data['totalfee']['value'], 2);

                if ($isTotalQuantity) {
                    $bucketsList = static::filterLandConstruction($data['aggregations']['buckets']);
                    $rtnList = LandCache::getListByHash(static::REDIS_LAND_CONSTRUCTION . $queryKey, $page, $pageSize);

                    if (empty($rtnList['data'])) {
                        if (!empty($bucketsList)) {
                            foreach ($bucketsList as $k => $v) {
                                LandCache::saveRecordByHash(static::REDIS_LAND_CONSTRUCTION . $queryKey, $k, $v);
                            }

                            foreach (
                                [
                                    'total_count' => $totalCount, 'total_area' => $totalArea, 'total_fee' => $totalFee
                                ] as $key => $item) {
                                LandCache::saveRecordByString(static::REDIS_LAND_CONSTRUCTION . '_' . $key . $queryKey, $id, $item);
                            }

                            $rtnList = LandCache::getListByHash(static::REDIS_LAND_CONSTRUCTION . $queryKey, $page, $pageSize);
                        }
                    }

                    $result['resultNum'] = (int)$rtnList['page']['count'];
                    $list = RedisUtil::RedisFilterList($rtnList['data']);
                } else {
                    $bucketsList = array_slice($data['aggregations']['buckets'], $from, $pageSize);
                    $list        = static::filterLandConstruction($bucketsList);
                }
            }
        }

        $result['resultSet'] = [
            'totalCount' => (int)$totalCount, 'totalArea' => (int)$totalArea, 'totalFee' => (int)$totalFee, 'list' => $list
        ];

        return $result;
    }

    /**
     * 过滤数据
     * @param array $buckets
     * @return array
     */
    protected static function filterLandConstruction($buckets = [])
    {
        if (!empty($buckets)) {
            $data = [];
            foreach ($buckets as $value) {
                $tmp['developer_uid'] = $value['developer_uid']['value'];
                $tmp['company_name']  = $value['key'];
                $tmp['total_count']   = $value['doc_count'];
                $tmp['total_area']    = $value['totalarea']['value'];
                $tmp['total_fee']     = $value['totalfee']['value'];
                $data[]               = $tmp;
            }

            return $data;
        }

        return [];
    }

    /**
     * 构建大数据拓客--开工数据-开工时间查询条件
     * @param string $takeLandDate
     * @return array
     */
    protected static function constructingLandConstructionDateQueryConditions(
        &$query = [],
        $contractStartTime = '',
        $contractEndTime = ''
    ) {
        // 构建时间周期查询
        if (!empty($contractStartTime)
            && !empty($contractEndTime)) {
            $query['bool']['must'][] = [
                'range' => [
                    'issuing_time' => [
                        'gte' => $contractStartTime,
                        'lte' => $contractEndTime
                    ]
                ]
            ];
        }
    }

    /**
     * 构建大数据拓客--开工数据-查询条件
     * @param array $query
     * @param string $region
     * @param string $contractStartTime
     * @param string $contractEndTime
     */
    protected static function constructingLandConstructionQueryConditions(
        &$query = [],
        $region = '',
        $contractStartTime = '',
        $contractEndTime = ''
    ) {

        if (!empty($contractStartTime) && !empty($contractEndTime)) {
            // 构建时间周期查询
            static::constructingLandConstructionDateQueryConditions(
                $query,
                date('Y-m-01', strtotime($contractStartTime)), date('Y-m-t', strtotime($contractEndTime)));
        }

        $bool = [];

        // 构建项目地区查询
        if (!empty($region)) {
            $region = explode(',', $region);
            foreach ($region as $item) {
                $bool[0]['bool']['should'][] = [
                    'match_phrase' => [
                        'city' => $item
                    ]
                ];
                $bool[0]['bool']['should'][] = [
                    'match_phrase' => [
                        'city_code.keyword' => $item
                    ]
                ];
                $bool[0]['bool']['should'][] = [
                    'match_phrase' => [
                        'province' => $item
                    ]
                ];
                $bool[0]['bool']['should'][] = [
                    'match_phrase' => [
                        'province_code.keyword' => $item
                    ]
                ];
            }
        }

        $query['bool']['must'][] = $bool;
    }

    /**
     * 构建大数据拓客--开工数据-聚合
     * @param int $size
     * @return array
     */
    protected static function constructingLandConstructionAggregation($page, $pageSize, $isTotalQuantity = true)
    {
        $size = $page * $pageSize;
        return [
            [
                'name' => 'totalarea',
                'options' => [
                    'sum' => [
                        'field' => 'area'
                    ]
                ]
            ],
            [
                'name' => 'totalfee',
                'options' => [
                    'sum' => [
                        'field' => 'contract_price'
                    ]
                ]
            ],
            [
            'name' => 'aggregations',
            'options' => [
                'terms' => [
                    'field' => 'company_name.keyword',
                    'order' => [
                        'totalarea' => 'desc'
                    ],
                    'size' => $isTotalQuantity ? pow(2,31) - 1 : $size
                ],
                'aggregations' => [
                    'developer_uid' => [
                        'max' => [
                            'field' => 'developer_uid'
                        ]
                    ],
                    'totalarea' => [
                        'sum' => [
                            'field' => 'area'
                        ]
                    ],
                    'totalfee' => [
                        'sum' => [
                            'field' => 'contract_price'
                        ]
                    ]
                ]
            ]
        ]
        ];
    }
    // =========================================== 市场数据-开工数据 ================================================ //

    // =========================================== 市场数据-项目数据 ================================================ //
    /**
     * 市场数据-项目数据列表
     * @param string $region
     * @param string $openingStartTime
     * @param string $openingEndTime
     * @param string $decorate
     * @param $page
     * @param $pageSize
     * @return array
     */
    public function getLandProjectList(
        $region = '',
        $openingStartTime = '',
        $openingEndTime = '',
        $decorate = '',
        $page,
        $pageSize,
        $id = 0,
        $isTotalQuantity = true
    ) {
        $page = max($page, 1);
        $query = [];

        // 构建查询条件
        static::constructingLandProjectQueryConditions(
            $query, $region, $openingStartTime, $openingEndTime, $decorate);

        $queryKey = md5(serialize($query));

        $rtnList = LandCache::getListByHash(static::REDIS_LAND_PROJECT . $queryKey, $page, $pageSize);

        if (!empty($rtnList['data'])) {
            $result['resultNum'] = (int)$rtnList['page']['count'];
            $list = RedisUtil::RedisFilterList($rtnList['data']);

            $additionalParms = [];

            foreach (
                [
                    'total_count', 'total_area', 'total_fee'
                ] as $item) {
                $additionalParms[
                preg_replace_callback('/_+([a-z])/', function($matches){
                    return strtoupper($matches[1]);
                }, $item)
                ] = LandCache::getRecordByString(static::REDIS_LAND_PROJECT . '_' . $item . $queryKey, $id);
            }
            extract($additionalParms);
        } else {
            $from = ($page - 1) * $pageSize;

            $include = ['uid', 'developer_uid', 'company_name', 'opening_time', 'decorate', 'area', 'price', 'created_time'];

            list($total, $data) = (new LandRepository())->queryLandProjectList(
                $query, $include, $aggregations = static::constructingLandProjectAggregation($page, $pageSize, $isTotalQuantity));

            $result = ['resultNum' => $data['aggregations']['sum_other_doc_count']??0, 'resultSet' => []];

            if (empty($aggregations)) {
                if (!empty($data)) {
                    foreach ($data as $values) {
                        $result['resultSet'][] = $values['_source'];
                    }
                }
            } else {

                $totalCount  = $total;
                $totalArea   = round($data['totalarea']['value'], 2);
                $totalFee    = round($data['totalfee']['value'] / 10000, 2);

                if ($isTotalQuantity) {
                    $bucketsList = static::filterLandProject($data['aggregations']['buckets']);
                    $rtnList = LandCache::getListByHash(static::REDIS_LAND_PROJECT . $queryKey, $page, $pageSize);

                    if (empty($rtnList['data'])) {
                        if (!empty($bucketsList)) {
                            foreach ($bucketsList as $k => $v) {
                                LandCache::saveRecordByHash(static::REDIS_LAND_PROJECT . $queryKey, $k, $v);
                            }

                            foreach (
                                [
                                    'total_count' => $totalCount, 'total_area' => $totalArea, 'total_fee' => $totalFee
                                ] as $key => $item) {
                                LandCache::saveRecordByString(static::REDIS_LAND_PROJECT . '_' . $key . $queryKey, $id, $item);
                            }

                            $rtnList = LandCache::getListByHash(static::REDIS_LAND_PROJECT . $queryKey, $page, $pageSize);
                        }
                    }

                    $result['resultNum'] = (int)$rtnList['page']['count'];
                    $list = RedisUtil::RedisFilterList($rtnList['data']);
                } else {
                    $bucketsList = array_slice($data['aggregations']['buckets'], $from, $pageSize);
                    $list        = static::filterLandProject($bucketsList);
                }
            }
        }

        $result['resultSet'] = [
            'totalCount' => (int)$totalCount, 'totalArea' => (int)$totalArea, 'totalFee' => (int)$totalFee, 'list' => $list
        ];

        return $result;
    }

    /**
     * 过滤数据
     * @param array $buckets
     * @return array
     */
    protected static function filterLandProject($buckets = [])
    {
        if (!empty($buckets)) {
            $data = [];
            $types = ['毛坯', '非毛坯'];
            foreach ($buckets as & $value) {
                $tmp['developer_uid'] = $value['developer_uid']['value'];
                $tmp['company_name']  = $value['key'];
                $tmp['total_count']   = $value['doc_count'];
                $tmp['totalarea']     = $value['totalarea']['value'];

                $decorates = $value['decorate']['buckets'];

                $merges = $newDecorate = [];

                if (!empty($decorates)) {
                    foreach ($decorates as $key => $item) {
                        $type = current(explode(',', $item['key']));
                        if (in_array($type, $types)) {
                            $merges[] = ['key' => $type, 'doc_count' => $item['doc_count']];
                        }
                    }

                    foreach ($types as $v) {
                        $docNum = static::mergeDecorate($v, $merges);
                        if (!empty($docNum)) {
                            $newDecorate[] = ['key' => $v, 'doc_count' => $docNum];
                        }
                    }
                }

                $value['decorate']['buckets'] = !empty($newDecorate) ? $newDecorate : [];

                $tmp['decorate'] = $value['decorate']['buckets'];
                $data[]          = $tmp;
            }

            return $data;
        }

        return [];
    }

    /**
     * 合并装修状况
     * @param string $name
     * @param array $decorates
     * @return int
     */
    protected static function mergeDecorate(
        $name = '',
        $merges = []
    ) {
        $docNum = 0;
        if (!empty($name) && !empty($merges)) {
            if (!empty($merges)) {
                foreach ($merges as $key => $item) {
                    if ($item['key'] == $name) {
                        $docNum += $item['doc_count'];
                    }
                }
            }
        }

        return $docNum;
    }

    /**
     * 构建大数据拓客--项目数据-开盘时间查询条件
     * @param string $takeLandDate
     * @return array
     */
    protected static function constructingLandProjectDateQueryConditions(
        &$query = [],
        $openingStartTime = '',
        $openingEndTime = ''
    ) {
        // 构建时间周期查询
        if (!empty($openingStartTime)
            && !empty($openingEndTime)) {
            $query['bool']['must'][] = [
                'range' => [
                    'opening_time' => [
                        'gte' => $openingStartTime,
                        'lte' => $openingEndTime
                    ]
                ]
            ];
        }
    }

    /**
     * 构建大数据拓客--项目数据-查询条件
     * @param array $query
     * @param string $region
     * @param string $openingStartTime
     * @param string $openingEndTime
     * @param string $decorate
     */
    protected static function constructingLandProjectQueryConditions(
        &$query = [],
        $region = '',
        $openingStartTime = '',
        $openingEndTime = '',
        $decorate = ''
    ) {

        if (!empty($openingStartTime) && !empty($openingEndTime)) {
            // 构建时间周期查询
            static::constructingLandProjectDateQueryConditions(
                $query,
                date('Y-m-01', strtotime($openingStartTime)), date('Y-m-t', strtotime($openingEndTime)));
        }

        $bool = [];

        // 构建项目地区查询
        if (!empty($region)) {
            $region = explode(',', $region);
            foreach ($region as $item) {
                $bool[0]['bool']['should'][] = [
                    'match_phrase' => [
                        'city' => $item
                    ]
                ];
                $bool[0]['bool']['should'][] = [
                    'match_phrase' => [
                        'city_code.keyword' => $item
                    ]
                ];
                $bool[0]['bool']['should'][] = [
                    'match_phrase' => [
                        'province' => $item
                    ]
                ];
                $bool[0]['bool']['should'][] = [
                    'match_phrase' => [
                        'province_code.keyword' => $item
                    ]
                ];
            }
        }

        // 构建装修查询
        if (!empty($decorate) && $decorate != '全部') {
            $decorates = explode(',', $decorate);
            foreach ($decorates as $decorate) {
                $bool[1]['bool']['should'][] = [
                    'match_phrase' => [
                        'decorate.keyword' => $decorate
                    ]
                ];
            }
        }
//        else {
//            $bool[1]['bool']['should'][] = [
//                'match_phrase' => [
//                    'decorate.keyword' => '毛坯'
//                ]
//            ];
//            $bool[1]['bool']['should'][] = [
//                'match_phrase' => [
//                    'decorate.keyword' => '非毛坯'
//                ]
//            ];
//        }

        $query['bool']['must'][] = $bool;
    }

    /**
     * 构建大数据拓客--项目数据-聚合
     * @param int $size
     * @return array
     */
    protected static function constructingLandProjectAggregation($page, $pageSize, $isTotalQuantity = true)
    {
        $size = $page * $pageSize;
        return [
            [
                'name' => 'totalarea',
                'options' => [
                    'sum' => [
                        'field' => 'area'
                    ]
                ]
            ],
            [
                'name' => 'totalfee',
                'options' => [
                    'sum' => [
                        'field' => 'total_price'
                    ]
                ]
            ],
            [
            'name' => 'aggregations',
            'options' => [
                'terms' => [
                    'field' => 'company_name.keyword',
                    'order' => [
                        'totalarea' => 'desc'
                    ],
                    'size' => $isTotalQuantity ? pow(2,31) - 1 : $size
                ],
                'aggregations' => [
                    'developer_uid' => [
                        'max' => [
                            'field' => 'developer_uid'
                        ]
                    ],
                    'totalarea' => [
                        'sum' => [
                            'field' => 'area'
                        ]
                    ],
                    'decorate' => [
                        'terms' => [
                            'field' => 'decorate.keyword',
                            'size' => pow(2,31) - 1
                        ],
                    ]
                ]
            ]
        ]
        ];
    }
    // =========================================== 市场数据-项目数据 ================================================ //

    // ====================================== 市场数据-近3个月初次拿地企业 ========================================== //
    /**
     * 构建近3个月初次拿地企业列表
     * @param $page
     * @param $pageSize
     * @return array
     */
    public function getFirsttimeLandHoldingEnterprisesList($page, $pageSize) {
        $page = max($page, 1);
        $query = [];

        // 构建查询条件
        static::constructingFirsttimeLandHoldingEnterprisesQueryConditions($query);

        $from = ($page - 1) * $pageSize;

        $include = ['uid', 'developer_uid', 'company_name', 'land_usage', 'take_land_price', 'area', 'take_land_date'];

        list($total, $data) = (new LandRepository())->queryLandTakeList(
            $query, $include, $aggregations = static::constructingFirsttimeLandHoldingEnterprisesAggregation());

        $result = ['resultNum' => $data['aggregations']['sum_other_doc_count']??0, 'resultSet' => []];

        if (empty($aggregations)) {
            if (!empty($data)) {
                foreach ($data as $values) {
                    $result['resultSet'][] = $values['_source'];
                }
            }
        } else {
            $bucketsList = array_slice($data['aggregations']['buckets'], $from, $pageSize);
            $result['resultSet'] = [
                'list' => static::filterFirsttimeLandHoldingEnterprises($bucketsList)
            ];
        }

        return $result;
    }

    /**
     * 过滤数据
     * @param array $buckets
     * @return array
     */
    protected static function filterFirsttimeLandHoldingEnterprises($buckets = [])
    {
        if (!empty($buckets)) {
            $data = [];
            foreach ($buckets as $value) {
                $tmp['last_developer_uid'] = $value['last_developer_uid']['value'];

                $landTakeInfo = (new \business\datacenter\repositories\LandRepository())->getLandTakeOne([
                    'is_deleted' => 0,
                    'developer_uid' => $tmp['last_developer_uid']
                ], 'province, city, land_usage');

                $tmp['company_name']       = $value['key'];

                $tmp['region']             = (!empty($landTakeInfo['province']) || !empty($landTakeInfo['city']))
                    ? $landTakeInfo['province'] . ' ' . $landTakeInfo['city'] : '';

                $tmp['land_usage']         = $landTakeInfo['land_usage'];
                $tmp['total_area']         = $value['totalarea']['value'];
                $tmp['total_fee']          = $value['totalfee']['value'];
                $tmp['take_land_date']     = $value['last_take_land_date']['value_as_string'];
                $data[]                    = $tmp;
            }

            return $data;
        }

        return [];
    }

    /**
     * 构建近3个月初次拿地企业查询条件
     * @param array $query
     */
    protected static function constructingFirsttimeLandHoldingEnterprisesQueryConditions(
        &$query = []
    ) {
        $startTime = date('Y-m-d H:i:s', strtotime("-3 month", DateTimeUtils::time()));
        $endTime   = DateTimeUtils::now();
        // 构建时间周期查询
        static::constructingTakeLandDateQueryConditions(
            $query, $startTime, $endTime);
    }

    /**
     * 近3个月初次拿地企业查询-聚合
     * @param $page
     * @param $pageSize
     * @return array
     */
    protected static function constructingFirsttimeLandHoldingEnterprisesAggregation() {
        return [
            [
                'name' => 'aggregations',
                'options' => [
                    'terms' => [
                        'field' => 'company_name.keyword',
                        'order' => [
                            'last_take_land_date' => 'desc'
                        ],
                        'size' => pow(2,31) - 1
                    ],
                    'aggs' => [
                        'last_developer_uid' => [
                            'max' => [
                                'field' => 'developer_uid'
                            ]
                        ],
                        'totalarea' => [
                            'sum' => [
                                'field' => 'area'
                            ]
                        ],
                        'totalfee' => [
                            'sum' => [
                                'field' => 'take_land_price'
                            ]
                        ],
                        'last_take_land_date' => [
                            'max' => [
                                'field' => 'take_land_date'
                            ]
                        ],
                        'having' => [
                            'bucket_selector' => [
                                'buckets_path' => [
                                    'aggregations' => '_count',
                                    'totalfee' => 'totalfee'
                                ],
                                'script' => [
                                    'source' => 'params.aggregations == 1 && params.totalfee >= 0'
                                ]
                            ]
                        ]
                    ],
                ]
            ]
        ];
    }
    // ====================================== 市场数据-近3个月初次拿地企业 ========================================== //
}
